package br.quest.gps;

import java.util.Date;
import br.quest.models.Waypoint;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;

public class GPSListener implements LocationListener {

    private static GPSListener instance;
    private Waypoint bestLocation;
    private WaypointListener listener;
    private int maxDistance = 10;

    private GPSListener() {
    }

    public static GPSListener getInstance() {
        if (instance == null)
            instance = new GPSListener();
        return instance;
    }

    public void setWaypointListener(WaypointListener listener) {
        this.listener = listener;
    }

    public Waypoint getBestLocation() {
        return bestLocation;
    }

    @Override
    public void onLocationChanged(Location location) {
        if ((bestLocation == null && location != null) ||
                (location != null && isBetterLocation(location, bestLocation.getCoord()))) {
            bestLocation = new Waypoint(location, new Date());
            listener.onWaypointRead(bestLocation);
        }
    }

    @Override
    public void onProviderDisabled(String arg0) {
    }

    @Override
    public void onProviderEnabled(String arg0) {
    }

    @Override
    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
    }

    protected boolean isBetterLocation(Location newLocation, Location bestLocation) {
        if (bestLocation == null)
            return true;
        long timeDelta = newLocation.getTime() - bestLocation.getTime();
        boolean isNewer = timeDelta > 0;
        int accuracyDelta = (int) (newLocation.getAccuracy() - bestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > maxDistance;
        boolean isFromSameProvider = isSameProvider(newLocation.getProvider(), bestLocation.getProvider());
        if (accuracyDelta < 0)
            return true;
        else if (isNewer && !isLessAccurate)
            return true;
        else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
            return true;
        return false;
    }

    private boolean isSameProvider(String prov1, String prov2) {
        return (prov1 == null) ? prov2 == null : prov1.equals(prov2);
    }
}
